//Lindsay Ergenekan 
//ergenekl@onid.oregonstate.edu 
//CS311 - 400
//Homework 6 - Twin Primes


#include "hw5.h"

#define ISBITSET(x,i) ((x[i>>3] & (1<<(i&7)))!=0)
#define SETBIT(x,i) x[i>>3]|=(1<<(i&7));
#define CLEARBIT(x,i) x[i>>3]&=(1<<(i&7))^0xFF;

#define MAP_SIZE 100000

int main(int argc, char *argv[])
{

    char c;
    int n, i, j, k, sq_rt;
    pthread_attr_t attr;

    while ((c = getopt(argc, argv, "n:")) != -1)
    switch (c){ 
        case 'n':
  //          n = atoi(argv[2]);
        n =5;
            printf("n = %d \n", n);
            if(n < 2)
            {
                printf("Not a high enough range");  
                exit(2);         
            }
        }
////////////////////////////////////variable for the bit map
    unsigned char *bitMAP = (unsigned char *) malloc(MAP_SIZE * sizeof (unsigned char));
    pthread_t thread[n]; //variable to track the thread ids
    struct thread_info t_info[n]; //variable to pass in the info for sieve funciton 





    SETBIT(bitMAP, 0); //mark off 1 as non-prime

    for (i = 0; i < n; ++i)
    {
        t_info[i].bitMAP = bitMAP;
//        t_info[i].up_to_num = 
        pthread_mutex_init(&lock, NULL);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

        if (0 != pthread_create(&thread[i], NULL, sieve, (void*)&t_info[i]))
        {
            printf("Error in thread creation \n");
            exit(2);
        }
    }

/*
    for (int i <)
    sq_rt = sqrt(5000);

    printf("sq_rt %d \n", sq_rt);
    SETBIT(flags, 0); //mark off 1 as non-prime

    for(i = 2; i <= sq_rt; i++)
        if(!ISBITSET(flags,i))
            for (j = i*i; j <= 5000; j += i)
                if(!ISBITSET(flags, i)){
                        SETBIT(flags,j); 
                }

*/
                printf("past the create stage\n");
//////////////////////////////////////////////////////////join all the threads again 
    for (i = 0; i<n; ++i){
    
        pthread_join(thread[i], NULL); 
    }
    
    printf("past the join stage\n");
    sq_rt = sqrt(5000);

    for ( i = 3; i < (sq_rt-2); ++i ){
        if (!ISBITSET(bitMAP, i) && !ISBITSET(bitMAP,(i+2))){
                printf("PRIME %d !\n", i);
            }}


return 0; 
}

/*
void * sieve(void *arg)
{
    pthread_mutex_lock(&lock);

    int i, j, sq_rt;
    int up_to_num; //varialbe to record where to end
    struct thread_info * bitMAP; //set up  the struct varialbe to recevei the argument
    unsigned char * map; //declare the bitmap (map) varible
    bitMAP = (thread_info *) arg; //cast the void * argument to the thread info struct type
    map = bitMAP->bitMAP; //set the bit map 
    up_to_num = bitMAP->up_to_num; //set the number to be read
 //   sq_rt = sqrt(5000);

    printf("up to num %d \n", up_to_num);
    
    pthread_mutex_unlock(&lock);
    pthread_exit((void*)0);//exit the thread

}

*/

void * sieve(void *arg)
{
    pthread_mutex_lock(&lock);

    int i, j, sq_rt;
    int up_to_num; //varialbe to record where to end
    struct thread_info * bitMAP;
    unsigned char * map;
    bitMAP = (thread_info *) arg;
    map = bitMAP->bitMAP;
    up_to_num = bitMAP->up_to_num;
    sq_rt = sqrt(5000);

    printf("sq_rt %d \n", sq_rt);


    for(i = 2; i <= sq_rt; i++)
    {
        if(!ISBITSET(map,i))
        {
            for (j = i*i; j <= 5000; j += i)
            {
                if(!ISBITSET(map, i)){
//                    pthread_mutex_lock();
                        SETBIT(map,j); 
//                    pthread_mutex_unlock();
                }    
            }
        }
    }
        pthread_mutex_unlock(&lock);
        pthread_exit((void*)0);//exit the thread

}
